#include<iostream>
#include<thread>
#include<vector>
#include<list>
#include <mutex>
using namespace std;

/*
设计模式概述：
	定义：写代码的一些方法（与常规写法不一致）程序灵活，维护方便，但是别人接管不容器
	用这个理念写成的代码很晦涩
	起源：外国人在写大项目时把开发经验，模块划分经验，总结成设计模式
	在中国，有人拿项目硬往设计模式上套（即便是一个小项目），本末倒置

	单例设计模式使用的频率比较高
	单例：整个项目中，有某个或某些特殊的类，属于该类的对象，我只能创建一个
		无法创建多个
	单例类：保证生成的对象只有一个

单例设计模式的数据共享问题分析解决
	//在主线程中创建单例类对象
	//在后续过程中只读，这是安全的
	
	如果在子线程中创建单例对象
	可能会面临GetInstance（）互斥
	通过内置的锁进行保护，同时需要用到双重锁定来提高效率

call-once（）函数模板，	cpp11引入的函数，	参数2：函数名
	功能：保护 参数2的函数 只被调用一次，可以用来解决多线程中多次调用函数问题
	具备互斥量的能力，而且效率比互斥量高
	要与once-flag标记结合使用（once-flag是结构体）
	call-once通过once-flag识别参数2函数是否已经被调用
	调用call-once成功后他会把once-flag设置成已调用状态
	再次调用call-once时只要once-flag被设置成已调用状态，那么参数2函数就不会被再次调用


*/


//定义一个保护new对象的互斥量
mutex resouce_mutex;

//定义标记（一般在类内）
once_flag g_flag;


//单例类
class MyCAS {


public: 
// 	   定义只被调用一次的函数
	static void CreateInstance() {

	}
	//私有构造函数
private:
	MyCAS() {

	}

public:
	static MyCAS* GetInstance() {

	//	//两层if，双重锁定（双重检查）
	//	//第一次if条件判断时，myinstance可能已经被new过了（线程切换问题，线程1判断后进入new环节时
	//	//线程2切入，此时线程2判断的if条件也成立，也会进入new环节）
	//	//依次，只要对象被真正创建了，这个条件必定不成立，只有第一次线程争着创建的时候，才可能不成立
	//	//进入加锁、第二层if判断的环节
	//	if (my_instance == NULL) {

	//		//自动加锁
	//		//放在if之前
	//		//但是效率较慢，因为这个锁只在创建my_instance时才有意义，但是我们每次都会加锁
	//		//解决方案：双重锁定
	//		unique_lock<mutex> mymutex(resouce_mutex);

	//		if (my_instance == NULL) {

	//			//共享代码
	//			//可能被多次执行,对一个变量多次new新的对象，造成线程的二义性
	//			// 程序报错
	//			//需要一个互斥量解决问题
	//			my_instance = new MyCAS();

	//			//定义静态变量，用来回收指针
	//			//在函数执行完后，cl被释放，而cl的析构函数内有释放指针的操作
	//			static CGarhuishou cl;

	//		}
	//	}
		//利用callonce代替上面代码
		call_once(g_flag, CreateInstance);
		return my_instance;
	}

	//类中套类，定义垃圾回收类
	//用来释放对象
	class CGarhuishou {
	public:
		~CGarhuishou()
		{
			//析构时，如果my
			if (MyCAS::my_instance != NULL) {
				delete MyCAS::my_instance;
				MyCAS::my_instance == NULL;
			}
		}
	};

	void func() {
		cout << "测试" << endl;
	}

private:
	//静态成员变量
	static MyCAS* my_instance;
};
//类中静态变量的初始化
MyCAS* MyCAS::my_instance = NULL;



//线程入口函数
void mythread() {
	cout << "我的线程开始执行了"<<endl;

	//出现问题
	MyCAS* pa = MyCAS::GetInstance();
	cout << "我的线程执行完毕了" << endl;
	return;
}



int main(int argc, char** argv) {
	
	//返回相同指针，pa和pb的对象相同，所以是单例
	MyCAS* p_a = MyCAS::GetInstance();
	MyCAS* p_b = MyCAS::GetInstance();


	//入口函数相同的两个线程
	//这导致类中new对象的时候被多次执行
	thread mt(mythread);
	thread mt2(mythread);
	mt.join();
	mt.join();



}